package com.ayf.payment.game.api.utils;

import com.ayf.payment.game.api.exception.InvalidEncryptedKeyException;
import com.swwx.charm.commons.lang.utils.LogPortal;
import org.apache.commons.lang.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

/**
 * @author admin
 * @Title: AESUtil
 * @Copyright: Copyright (c) 2018
 * @Description: <br>
 * @Company: 123.com
 * @Created on 2019/3/4上午11:13
 */
public class AESUtil {
    public static final String PASSWORD="20191217q1w2e3r4";
    private static final String ALGORITHM_ECB = "AES/ECB/PKCS5Padding";
    private static final String ALGORITHM_CBC = "AES/CBC/PKCS5Padding";

    /**
     * aes加密-256位
     */
    public static String aes256Encrypt(String content, String password) throws InvalidEncryptedKeyException {
        if (StringUtils.isBlank(password)) {
            throw new InvalidEncryptedKeyException("password is not null");
        }
        if (password.length() !=16) {
            LogPortal.error("AESUtil-256加密异常 密码是[{}] is not 16 bytes",password);
            throw new InvalidEncryptedKeyException("password must be is 16 bytes");
        }
        if (StringUtils.isBlank(content)) {
            return null;
        }
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance("AES");
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(password.getBytes());
            keyGen.init(256, secureRandom);
            SecretKey secretKey = keyGen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance(ALGORITHM_CBC);
            IvParameterSpec iv = new IvParameterSpec(password.getBytes());//使用CBC模式，需要一个向量iv，可增加加密算法的强度
            cipher.init(Cipher.ENCRYPT_MODE, key,iv);
            return Base64.encode(cipher.doFinal(content.getBytes("UTF-8")));
        } catch (Exception e) {
            LogPortal.error("AESUtil-256加密异常 加密内容[{}],password [{}]",e,content,password);
            return null;
        }
    }

    /**
     * aes解密-256位
     * @param encryptContent
     * @param password
     * @param illegalArgument
     * @return
     * @throws InvalidEncryptedKeyException
     * @throws IllegalArgumentException
     */
    public static String aes256Decrypt(String encryptContent, String password,String illegalArgument) throws InvalidEncryptedKeyException, IllegalArgumentException {
        if (StringUtils.isBlank(password)) {
            throw new InvalidEncryptedKeyException("password is not null");
        }
        if (password.length() !=16) {
            LogPortal.error("AESUtil-256解密异常 参数[{}]的密码是[{}] is not 16 bytes",illegalArgument,password);
            throw new InvalidEncryptedKeyException("password must be is 16 bytes");
        }
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance("AES");
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(password.getBytes());
            keyGen.init(256, secureRandom);
            SecretKey secretKey = keyGen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance(ALGORITHM_CBC);
            IvParameterSpec iv = new IvParameterSpec(password.getBytes());//使用CBC模式，需要一个向量iv，可增加加密算法的强度
            cipher.init(Cipher.DECRYPT_MODE, key,iv);
            String result  = new String(cipher.doFinal(Base64.decode(encryptContent)));
            return result;
        } catch (Exception e) {
            // null 解密的时候 会出现以下的异常，空字符串解密则不出现异常
            if (e instanceof IllegalArgumentException && "Null input buffer".equals(e.getMessage())) {
                LogPortal.error("AESUtil-256解密异常 [{}] 加密原文内容为 null 系统默认返回 null",illegalArgument);
                return null;
            }
            LogPortal.error("AESUtil-256解密异常 [{}]未加密或加密错误,password [{}],encryptContent [{}]",e,illegalArgument,password,encryptContent);
            throw new IllegalArgumentException(illegalArgument+" 未加密或加密错误");
        }
    }

    /**
     * aes加密-128位
     */
    public static String aes128Encrypt(String content, String password) throws InvalidEncryptedKeyException {
        if (StringUtils.isBlank(password)) {
            throw new InvalidEncryptedKeyException("password is not null");
        }
        if (password.length() !=16) {
            throw new InvalidEncryptedKeyException("password must be is 16 bytes");
        }
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance("AES");
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(password.getBytes());
            keyGen.init(128, secureRandom);
            SecretKey secretKey = keyGen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance(ALGORITHM_ECB);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return Base64.encode(cipher.doFinal(content.getBytes("UTF-8")));
        } catch (Exception e) {
            LogPortal.error("AESUtil-128加密异常 加密内容[{}],password [{}]",e,content,password);
            return null;
        }
    }

    /**
     * aes解密-128位
     */
    public static String aes128Decrypt(String encryptContent, String password) throws InvalidEncryptedKeyException {
        if (StringUtils.isBlank(password)) {
            throw new InvalidEncryptedKeyException("password is not null");
        }
        if (password.length() !=16) {
            LogPortal.error("AESUtil-128解密异常 解密密码是[{}] is not 16 bytes",password);
            throw new InvalidEncryptedKeyException("password must be is 16 bytes");
        }
        String errrMsg = "未加密或加密错误";
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance("AES");
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(password.getBytes());
            keyGen.init(128, secureRandom);
            SecretKey secretKey = keyGen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance(ALGORITHM_ECB);
            cipher.init(Cipher.DECRYPT_MODE, key);
            return new String(cipher.doFinal(Base64.decode(encryptContent)));
        } catch (Exception e) {
            if (e instanceof IllegalArgumentException && "Null input buffer".equals(e.getMessage())) {
                errrMsg = "加密原文参数允许为空时，只能为空字符串，不允许null";
            }
            LogPortal.error("AESUtil-128解密异常 [{}]{},password [{}]",e,encryptContent,errrMsg,password);
            return null;
        }
    }
}
